package com.yj.web.WeChat.api;

import com.yj.web.WeChat.Message.WxXmlMessage;
import com.yj.web.WeChat.Message.WxXmlOutMessage;
import com.yj.web.util.Session.WxSessionManager;
import com.yj.web.util.WxErrorException;
import com.yj.web.util.WxErrorExceptionHandler;
import lombok.Data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Created by yanlinyang on 2017/9/10.
 */
@Data
public class WxMessageRouterRule {
    private final WxMessageRouter routerBuilder;

    private boolean async = true;

    private String fromUser;

    private String msgType;

    private String event;

    private String eventKey;

    private String content;

    private String rContent;

    private WxMessageMatcher matcher;

    private boolean reEnter = false;

    private List<WxMessageHandler> handlers = new ArrayList<WxMessageHandler>();

    private List<WxMessageInterceptor> interceptors = new ArrayList<WxMessageInterceptor>();

    public WxMessageRouterRule(WxMessageRouter routerBuilder) {
        this.routerBuilder = routerBuilder;
    }

    public WxMessageRouterRule async(boolean async) {
        this.async = async;
        return this;
    }

    public WxMessageRouterRule msgType(String msgType) {
        this.msgType = msgType;
        return this;
    }

    public WxMessageRouterRule event(String event) {
        this.event = event;
        return this;
    }

    public WxMessageRouterRule eventKey(String eventKey) {
        this.eventKey = eventKey;
        return this;
    }

    public WxMessageRouterRule content(String content) {
        this.content = content;
        return this;
    }

    public WxMessageRouterRule rContent(String regex) {
        this.rContent = regex;
        return this;
    }

    public WxMessageRouterRule fromUser(String fromUser) {
        this.fromUser = fromUser;
        return this;
    }

    public WxMessageRouterRule matcher(WxMessageMatcher matcher) {
        this.matcher = matcher;
        return this;
    }

    public WxMessageRouterRule interceptor(WxMessageInterceptor interceptor) {
        return interceptor(interceptor, (WxMessageInterceptor[]) null);
    }

    public WxMessageRouterRule interceptor(WxMessageInterceptor interceptor, WxMessageInterceptor... otherInterceptors) {
        this.interceptors.add(interceptor);
        if (otherInterceptors != null && otherInterceptors.length > 0) {
            for (WxMessageInterceptor i : otherInterceptors) {
                this.interceptors.add(i);
            }
        }
        return this;
    }

    public WxMessageRouterRule handler(WxMessageHandler handler) {
        return handler(handler, (WxMessageHandler[]) null);
    }

    public WxMessageRouterRule handler(WxMessageHandler handler, WxMessageHandler... otherHandlers) {
        this.handlers.add(handler);
        if (otherHandlers != null && otherHandlers.length > 0) {
            for (WxMessageHandler i : otherHandlers) {
                this.handlers.add(i);
            }
        }
        return this;
    }

    public WxMessageRouter end() {
        this.routerBuilder.getRules().add(this);
        return this.routerBuilder;
    }

    public WxMessageRouter next() {
        this.reEnter = true;
        return end();
    }

    protected WxXmlOutMessage service(WxXmlMessage wxMessage,
                                      WxService wxService,
                                      WxSessionManager sessionManager,
                                      WxErrorExceptionHandler exceptionHandler) {

        try {

            Map<String, Object> context = new HashMap<String, Object>();
            // 如果拦截器不通过
            for (WxMessageInterceptor interceptor : this.interceptors) {
                if (!interceptor.intercept(wxMessage, context, wxService, sessionManager)) {
                    return null;
                }
            }

            // 交给handler处理
            WxXmlOutMessage res = null;
            for (WxMessageHandler handler : this.handlers) {
                // 返回最后handler的结果
                res = handler.handle(wxMessage, context, wxService, sessionManager);
            }
            return res;
        } catch (WxErrorException e) {
            exceptionHandler.handle(e);
        }
        return null;
    }

    protected boolean test(WxXmlMessage wxMessage) {
        return
                (this.fromUser == null || this.fromUser.equals(wxMessage.getFromUser()))
                        &&
                        (this.msgType == null || this.msgType.toLowerCase().equals((wxMessage.getMsgType()==null?null:wxMessage.getMsgType().toLowerCase())))
                        &&
                        (this.event == null || this.event.toLowerCase().equals((wxMessage.getEvent()==null?null:wxMessage.getEvent().toLowerCase())))
                        &&
                        (this.eventKey == null || this.eventKey.toLowerCase().equals((wxMessage.getEventKey()==null?null:wxMessage.getEventKey().toLowerCase())))
                        &&
                        (this.content == null || this.content
                                .equals(wxMessage.getContent() == null ? null : wxMessage.getContent().trim()))
                        &&
                        (this.rContent == null || Pattern
                                .matches(this.rContent, wxMessage.getContent() == null ? "" : wxMessage.getContent().trim()))
                        &&
                        (this.matcher == null || this.matcher.match(wxMessage))
                ;
    }
}
